package com.example.demo.lock;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 使用redisTemplate模式要注意spring的配置，在大量并发下配置不当会导致宕机
 */
@Component("redisTemplateLock")
public class RedisTemplateLock implements RedisLock {

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public boolean lock(String lockValue, int seconds) {
        System.out.println("--------------lock--------------");
        final Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(lockValue, lockValue, 10, TimeUnit.SECONDS);
        return aBoolean;
    }

    @Override
    public boolean tryLock(String lockValue, int seconds) {
        for (;;){
            final Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(lockValue, lockValue, 10, TimeUnit.SECONDS);
            if (aBoolean){
                break;
            }
            //防止一直消耗 CPU
            try {
                Thread.sleep(1000) ;
            } catch (InterruptedException e) {
                e.printStackTrace();
                return  false;
            }
        }
        return true;
    }

    @Override
    public boolean release(String lock) {
        String luaScript = "if redis.call('get',KEYS[1]) == ARGV[1] then " + "return redis.call('del',KEYS[1]) else return 0 end";
        DefaultRedisScript<Long> defaultRedisScript = new DefaultRedisScript<>();
        defaultRedisScript.setResultType(Long.class);
        defaultRedisScript.setScriptText(luaScript);
        List<String> keys =new ArrayList<>();
        keys.add(lock);
        final Object eval = redisTemplate.execute(defaultRedisScript, keys, lock);


        /*RedisCallback<Long> callback = (connection) -> {
            Object nativeConnection = connection.getNativeConnection();
            // 集群模式
            if (nativeConnection instanceof LettuceConnection) {
                return (Long) ((LettuceConnection) nativeConnection).eval(luaScript, Collections.singletonList(lock), Collections.singletonList(lock));
            }
            // 单机模式
            else if (nativeConnection instanceof Jedis) {
                return (Long) ((Jedis) nativeConnection).eval(luaScript, Collections.singletonList(lock), Collections.singletonList(lock));
            }
            return 0L;
        };
        redisTemplate.execute(callback);*/
        return eval.equals(1L);
    }
}
